﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static PreventChess.ChessmanButton;

namespace PreventChess
{
    class BoardChess: Control
    {
        const float SQR2 = 1.414f;
        Color chess_color = Color.Red;

        private ChessmanArrowColor arrowColor = ChessmanArrowColor.RED;
        [Category("棋盘内棋子")]
        [Description("颜色")]
        public ChessmanArrowColor ArrowColor
        {
            get { return arrowColor; }
            set
            {
                arrowColor = value;
                SetChessmanColor(arrowColor);
                this.Invalidate();

            }
        }



        private ChessmanArrowType arrowType = ChessmanArrowType.ONE;

        [Category("棋盘内棋子")]
        [Description("样式")]
        public ChessmanArrowType ArrowType
        {
            get { return arrowType; }
            set
            {
                arrowType = value;
                this.Invalidate();
                //SetChessmanType(arrowType);

            }
        }

        private int deflection = 0;
        [Category("棋盘内棋子")]
        [Description("偏移")]
        public int Deflection
        {
            get { return deflection; }
            set
            {
                deflection = value;
                this.Invalidate();
            }
        }


        private  int arrowPenWidth = 6;
        [Category("棋盘内棋子")]
        [Description("箭头宽度")]
        public int ArrowPenWidth
        {
            get { return arrowPenWidth; }
            set
            {
                arrowPenWidth = value;
              
            }
        }

        private Point blockLocation = new Point(0,0);
        [Category("棋盘内棋子")]
        [Description("格子位置")]
        public Point BlockLocation
        {
            get { return blockLocation; }
            set
            {
                blockLocation = value;
                
            }
        }

        private bool isAbleMove = true;
        [Category("棋盘内棋子")]
        [Description("是否可以移动")]
        public bool IsAbleMove
        {
            get { return isAbleMove; }
            set
            {
                isAbleMove = value;
                this.Invalidate();
            }
        }

        public BoardChess()
        {
            this.SetStyle(ControlStyles.ResizeRedraw, true);//空间大小改变时，控件会重绘
            this.SetStyle(ControlStyles.AllPaintingInWmPaint , true);// 减少闪烁
            this.ArrowPenWidth = FrmChessBoard.ARROW_PEN_WIDTH;
        }


        protected override void OnPaint(PaintEventArgs e)
        {

            base.OnPaint(e);

            int width = this.Width;
            int height = this.Height;
            int radius = width < height ? width : height;//以最短的边最为圆的直径

            Graphics graphics = this.CreateGraphics();
            //graphics.Clear( Color .FromArgb (255,240,240,240) );
            Rectangle rectangle = new Rectangle(0, 0, radius, radius);


            graphics.SmoothingMode = SmoothingMode.AntiAlias;//消除锯齿
            Brush brush = new SolidBrush(chess_color);//指定画刷的颜色
            graphics.FillEllipse(brush, new Rectangle(0, 0, radius, radius));//填充一个圆


            Pen pen = new Pen(chess_color, 2);//指定画笔的颜色和线宽
            graphics.DrawEllipse(pen, rectangle);//绘制圆的边界

            DrawChess(graphics);

            //string text = this.Text;

            string text;
            if (!isAbleMove)
            {
                text = "本回合禁止移动";
            }
            else
            {
                text = "";
            }
            brush = new SolidBrush(Color.Black);//指定画刷画文本的颜色
            Font font = this.Font;


            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;//字符水平对齐方式
            sf.LineAlignment = StringAlignment.Center;//字符垂直对齐方式
            graphics.DrawString(text, font, brush, new RectangleF(0, 0, radius, radius), sf);


            #region  使控件的单击事件只在圆内触发，而不是在矩形控件范围内触发，消除在圆外和控件内的区域响应单机事件的bug
            GraphicsPath path = new GraphicsPath();
            path.AddEllipse(0, 0, radius, radius);
            this.Region = new Region(path);
            #endregion


            //font.Dispose();//当控件的size改变时，如果调用了 font.Dispose()，那么font.Height会报异常，因为没有重新实例化font类，导致DrawString会报参数无效，所以也可以不调用font.dispose，这样就可以不用捕获异常了
            brush.Dispose();
            pen.Dispose();
            graphics.Dispose();

        }

        void DrawChess(Graphics g)
        {
            switch (this.ArrowType)
            {
                case ChessmanArrowType.ONE:
                    DrawArrow(g, this.Deflection); // 画单个箭头 

                    break;
                case ChessmanArrowType.TWO_45:
                    DrawArrow(g, this.Deflection); // 画单个箭头 
                    DrawArrow(g, this.Deflection + 45); // 画单个箭头 

                    break;
                case ChessmanArrowType.TWO_90:
                    DrawArrow(g, this.Deflection); // 画单个箭头 
                    DrawArrow(g, this.Deflection + 90); // 画单个箭头 

                    break;
                case ChessmanArrowType.TWO_135:
                    DrawArrow(g, this.Deflection); // 画单个箭头 
                    DrawArrow(g, this.Deflection + 135); // 画单个箭头 

                    break;
                case ChessmanArrowType.TWO_180:
                    DrawArrow(g, this.Deflection); // 画单个箭头 
                    DrawArrow(g, this.Deflection + 180); // 画单个箭头 
                    break;
                case ChessmanArrowType.THREE_45:
                    DrawArrow(g, this.Deflection); // 画单个箭头 
                    DrawArrow(g, this.Deflection + 45); // 画单个箭头 
                    DrawArrow(g, this.Deflection + 90); // 画单个箭头 
                    break;
                case ChessmanArrowType.THREE_90:
                    DrawArrow(g, this.Deflection); // 画单个箭头 
                    DrawArrow(g, this.Deflection + 90); // 画单个箭头 
                    DrawArrow(g, this.Deflection + 180); // 画单个箭头 

                    break;
                case ChessmanArrowType.FOUR:
                    DrawArrow(g, this.Deflection); // 画单个箭头 
                    DrawArrow(g, this.Deflection + 90); // 画单个箭头 
                    DrawArrow(g, this.Deflection + 180); // 画单个箭头 
                    DrawArrow(g, this.Deflection + 270); // 画单个箭头 

                    break;
                case ChessmanArrowType.JUMP:
                    DrawArrowJump(g, this.Deflection);

                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// 绘制JUMP箭头
        /// </summary>
        /// <param name="g"></param>
        /// <param name="angle"></param>
        void DrawArrowJump(Graphics g,int angle) 
        {
            Pen pen = new Pen(Color.White, this.ArrowPenWidth);
            pen.StartCap = LineCap.Round;
            pen.EndCap = LineCap.ArrowAnchor;

            Brush brush = new SolidBrush(Color.White);

            if (angle >= 360)
            {
                angle = angle - 360;
            }
            switch (angle)
            {
                case 0:
                    g.DrawLine(pen, this.Width / 2 - pen.Width, this.Height / 2, this.Width - pen.Width * 2, this.Height/2);
                    g.FillEllipse(brush, new Rectangle(Width - ArrowPenWidth * 2 , Height / 2 - ArrowPenWidth , ArrowPenWidth * 2, ArrowPenWidth * 2));//填充一个圆
                   
                    break;
                case 45:
                    g.DrawLine(pen, this.Width / 2 - pen.Width, this.Height / 2 + pen.Width, this.Width/SQR2 , this.Height - this.Height/SQR2);
                    g.FillEllipse(brush, new Rectangle((int)(Width / SQR2 - ArrowPenWidth/2), (int)(Height - Height / SQR2 - ArrowPenWidth * 3 / 2), ArrowPenWidth * 2, ArrowPenWidth * 2));//填充一个圆
                   
                    break;
                case 90:
                    g.DrawLine(pen, this.Width / 2, this.Height / 2 + pen.Width, this.Width /2, pen.Width * 2);
                    g.FillEllipse(brush, new Rectangle(Width / 2 - ArrowPenWidth, ArrowPenWidth/2, ArrowPenWidth * 2, ArrowPenWidth * 2));//填充一个圆

                    break;
                case 135:
                    g.DrawLine(pen, this.Width / 2 + pen.Width, this.Height / 2 + pen.Width, this.Width - this.Width / SQR2 , this.Height - this.Height / SQR2);
                    g.FillEllipse(brush, new Rectangle((int)(Width - Width / SQR2 - ArrowPenWidth * 3 / 2), (int)(Height - this.Height / SQR2 - ArrowPenWidth * 3 / 2), ArrowPenWidth * 2, ArrowPenWidth * 2));//填充一个圆

                    break;
                case 180:
                    g.DrawLine(pen, this.Width / 2 + pen.Width, this.Height / 2, pen.Width * 2, this.Height / 2);
                    g.FillEllipse(brush, new Rectangle(ArrowPenWidth/2, Height / 2 - ArrowPenWidth, ArrowPenWidth * 2, ArrowPenWidth * 2));//填充一个圆

                    break;
                case 225:
                    g.DrawLine(pen, this.Width / 2 + pen.Width, this.Height / 2 - pen.Width, this.Width - this.Width / SQR2 , this.Height / SQR2);
                    g.FillEllipse(brush, new Rectangle((int)(Width - this.Width / SQR2 - ArrowPenWidth) , (int)(Height / SQR2), ArrowPenWidth * 2, ArrowPenWidth * 2));//填充一个圆

                    break;
                case 270:
                    g.DrawLine(pen, this.Width / 2, this.Height / 2 -pen.Width, this.Width/2 , this.Height - pen.Width * 2);
                    g.FillEllipse(brush, new Rectangle(Width / 2 - ArrowPenWidth * 3 / 2, Height - ArrowPenWidth * 2, ArrowPenWidth * 2, ArrowPenWidth * 2));//填充一个圆

                    break;
                case 315:
                    g.DrawLine(pen, this.Width / 2 - pen.Width, this.Height / 2 - pen.Width, this.Width / SQR2 , this.Height / SQR2);
                    g.FillEllipse(brush, new Rectangle((int)(Width / SQR2), (int)(Height / SQR2), this.ArrowPenWidth * 2, this.ArrowPenWidth * 2));//填充一个圆


                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// 绘制指定方向的箭头
        /// </summary>
        /// <param name="g"></param>
        /// <param name="angle"></param>
        void DrawArrow(Graphics g, int angle)
        {
            Pen pen = new Pen(Color.White, this.ArrowPenWidth);
            pen.StartCap = LineCap.Round;
            pen.EndCap = LineCap.ArrowAnchor;

            if (angle >= 360)
            {
                angle = angle - 360;
            }
            switch (angle)
            {
                case 0:
                    g.DrawLine(pen, this.Width / 2, this.Height / 2, this.Width - pen.Width, this.Height / 2);

                    break;
                case 45:
                    g.DrawLine(pen, this.Width / 2, this.Height / 2, this.Width / SQR2 + pen.Width, this.Height - this.Height / SQR2 - pen.Width);

                    break;
                case 90:
                    g.DrawLine(pen, this.Width / 2, this.Height / 2, this.Width / 2, pen.Width);

                    break;
                case 135:
                    g.DrawLine(pen, this.Width / 2, this.Height / 2, this.Width - this.Width / SQR2 - pen.Width, this.Height - this.Height / SQR2 - pen.Width);

                    break;
                case 180:
                    g.DrawLine(pen, this.Width / 2, this.Height / 2, pen.Width, this.Height / 2);

                    break;
                case 225:
                    g.DrawLine(pen, this.Width / 2, this.Height / 2, this.Width - this.Width / SQR2 - pen.Width, this.Height / SQR2 + pen.Width);

                    break;
                case 270:
                    g.DrawLine(pen, this.Width / 2, this.Height / 2, this.Width / 2, this.Height - pen.Width);

                    break;
                case 315:
                    g.DrawLine(pen, this.Width / 2, this.Height / 2, this.Width / SQR2 + pen.Width, this.Height / SQR2 + pen.Width);


                    break;
                default:
                    break;
            }
        }


        void SetChessmanColor(ChessmanArrowColor color)
        {
            switch (color)
            {
                case ChessmanArrowColor.RED:
                    chess_color = Color.Red;
                    break;
                case ChessmanArrowColor.BLUE:
                    chess_color = Color.DeepSkyBlue;

                    break;
                case ChessmanArrowColor.PURPLE:
                  
                    chess_color = Color.MediumPurple;

                    break;
                case ChessmanArrowColor.YELLOW:
                    chess_color = Color.Khaki;

                    break;
                case ChessmanArrowColor.GREEN:
                    chess_color = Color.Green;

                    break;
                case ChessmanArrowColor.ORANGE:
                    chess_color = Color.Orange;

                    break;
                default:
                    break;
            }
        }

 


    }
}
